package demo.java.util.concurrent;

import com.taobao.api.internal.util.NamedThreadFactory;
import demo.java.lang.ThreadDemo;
import demo.vo.common.TimeCost;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * CompletableFuture 的优势：
 *
 * <li>更好的异常处理：可以更细致地控制异常处理流程。
 * <li>函数式编程风格：支持链式调用和组合操作，代码更加简洁。
 * <li>灵活的任务编排：可以轻松地组合和编排多个异步任务。
 * <li>改进的性能：相比传统的 Future，CompletableFuture 提供了更高效的非阻塞操作。
 */
public class CompletableFutureDemo {

    private static Logger logger = LoggerFactory.getLogger(CompletableFutureDemo.class);

    public static final ExecutorService EXECUTOR =
            Executors.newFixedThreadPool(20, new NamedThreadFactory("query", true));

    @Test
    public void testCompletableFuture() {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
                    // 模拟长时间运行的任务
                    ThreadDemo.safeSleep(1000);
                    logger.info("业务处理中");
                    return "Hello";
                }).thenApply(s -> s + " World")
                .thenApply(String::toUpperCase);

        // 非阻塞地获取结果
        future.thenAccept(System.out::println);

        // 等待完成
        future.join();

    }

    @Test
    public void testCompletableFuture2() {
        TimeCost t0 = new TimeCost();
        String[] names = {"Fred Edwards", "Anna Cox", "Deborah Patterson", "Ruth Torres", "Shawn Powell",
                "Rose Thompson", "Rachel Barnes", "Eugene Ramirez", "Earl Flores", "Janice Reed", "Sarah Miller",
                "Patricia Kelly", "Carl Hall", "Craig Wright", "Martha Phillips", "Thomas Howard", "Steve Martinez",
                "Diana Bailey", "Kathleen Hughes", "Russell Anderson", "Theresa Perry"};
        List<CompletableFuture<String>> futures = Arrays.stream(names)
                .map(str -> CompletableFuture.supplyAsync(() -> {
                    ThreadDemo.safeSleep(1000);
                    logger.info(Thread.currentThread().getName());
                    return str + "1000";
                }, EXECUTOR)).collect(Collectors.toList());
        List<String> ls = futures.stream()
                .map(CompletableFuture::join)
                .collect(Collectors.toList());
        System.out.println("耗时：" + t0.cost() + " ms");
        System.out.println(ls.size() + ": " + ls);
    }
}
